=begin pod

=TITLE class Capture

=SUBTITLE Argument list suitable for passing to a Signature

=for code :skip-test
class Capture does Positional does Associative { }

A Capture is a container for passing arguments to a code object.  Captures
are the flip-side of Signatures – Captures at the caller define arguments,
while Signatures at the callee define parameters.

When you call C<print $a, $b>, the C<$a, $b> part is a Capture.

Captures contain a list-like part for positional arguments and a hash-like
part for named arguments.  For the named arguments, Captures use a slightly
different I<syntax> than a normal List.  There are two easy ways to make a
named argument: 1) use an unquoted key naming a parameter, followed by
C«=>», followed by the argument and 2) use a colon-pair literal named
after the parameter:

    say unique 1, -2, 2, 3, as => { abs $_ };   # OUTPUT: «(1 -2 3)␤»
    # ... is the same thing as:
    say unique 1, -2, 2, 3, :as({ abs $_ });    # OUTPUT: «(1 -2 3)␤»
    # Be careful not to quote the name of a named parameter:
    say unique 1, -2, 2, 3, 'as' => { abs $_ };
    # OUTPUT: «(1 -2 2 3 as => -> ;; $_? is raw { #`(Block|78857320) ... })␤»

A stand-alone Capture can also be made, stored, and used later.  A literal
Capture can be created by prefixing a term with a backslash C<\>.
Commonly, this term will be a List of terms, from which any Pair
literal will be placed in the named part, and all other terms will be
placed in the positional part.

    my $c = \(42);          # Capture with one positional part
    $c = \(1, 2, a => 'b'); # Capture with two positional and one named parts

To use such a Capture, you may use C<'|'> before it in a function call, and it
will be as if the values in the Capture were passed directly to the function
as arguments – named arguments will be passed as named arguments and positional
arguments will be passed as positional arguments.  You may re-use the Capture
as many times as you want, even with different functions.

    my $c = \(4, 2, 3);
    reverse(|$c).say; # OUTPUT: «3 2 4␤»
    sort(5,|$c).say;  # OUTPUT: «2 3 4 5␤»

Inside a Signature, a Capture may be created by prefixing a sigilless parameter
with a vertical bar C<|>.  This packs the remainder of the argument list
into that parameter.

    f(1, 2, 3, a => 4, b => 5);
    sub f($a, |c) {
        # c  is  \(2, 3, a => 4, b => 5)
    }

Note that Captures are still Lists in that they may contain containers, not
just values:

    my $b = 1;
    my $c = \(4, 2, $b, 3);
    sort(|$c).say;        # OUTPUT: «1 2 3 4␤»
    $b = 6;
    sort(|$c).say;        # OUTPUT: «2 3 4 6␤»

=head1 Methods

=head2 method list

Defined as:

    method list(Capture:D: --> Positional)

Returns the positional part of the Capture.

    my Capture $c = \(2, 3, 5, apples => (red => 2));
    say $c.list;                                      # OUTPUT: «(2 3 5)␤»

=head2 method hash

Defined as:

    method hash(Capture:D: --> Associative)

Returns the named/hash part of the Capture.

    my Capture $c = \(2, 3, 5, apples => (red => 2));
    say $c.hash; # OUTPUT: «Map.new((:apples(:red(2))))␤»

=head2 method elems

Defined as:

    method elems(Capture:D: --> Int:D)

Returns the number of positional elements in the Capture.

    my Capture $c = \(2, 3, 5, apples => (red => 2));
    say $c.elems;                                     # OUTPUT: «3␤»

=head2 method keys

Defined as:

    multi method keys(Capture:D: --> Seq:D)

Returns a L<Seq|/type/Seq> containing all positional keys followed by all
named keys. For positional arguments the keys are the respective arguments
ordinal position starting from zero.

    my $capture = \(2, 3, 5, apples => (red => 2));
    say $capture.keys;                                # OUTPUT: «(0 1 2 apples)␤»

=head2 method values

Defined as:

    multi method values(Capture:D: --> Seq:D)

Returns a L<Seq|/type/Seq> containing all positional values followed by all
named argument values.

    my $capture = \(2, 3, 5, apples => (red => 2));
    say $capture.values;                              # OUTPUT: «(2 3 5 red => 2)␤»

=head2 method kv

Defined as:

    multi method kv(Capture:D: --> Seq:D)

Returns a L<Seq|/type/Seq> of alternating L<keys|#method_keys> and
L<values|#method_values>. The positional keys and values, if any, comes
first followed by the named keys and values.

    my $capture = \(2, 3, apples => (red => 2));
    say $capture.kv;                                  # OUTPUT: «(0 2 1 3 apples red => 2)␤»

=head2 method pairs

Defined as:

    multi method pairs(Capture:D: --> Seq:D)

Returns all arguments, the positional followed by the named, as a
L<Seq|/type/Seq> of L<Pairs|/type/Pair>. Positional arguments have
their respective ordinal value, starting at zero, as key while the
named arguments have their names as key.

    my Capture $c = \(2, 3, apples => (red => 2));
    say $c.pairs;                                     # OUTPUT: «(0 => 2 1 => 3 apples => red => 2)␤»

=head2 method antipairs

Defined as:

    multi method antipairs(Capture:D: --> Seq:D)

Returns all arguments, the positional followed by the named, as a
L<Seq|/type/Seq> of L<pairs|/type/Pair> where the keys and values
have been swapped, i.e. the value becomes the key and the key becomes
the value. This behavior is the opposite of the L<pairs|#method_pairs>
method.

    my $capture = \(2, 3, apples => (red => 2));
    say $capture.antipairs;                           # OUTPUT: «(2 => 0 3 => 1 (red => 2) => apples)␤»

=head2 method Bool

Defined as:

    method Bool(Capture:D: --> Bool:D)

Returns C<True> if the Capture contains at least one named or one
positional argument.

    say \(1,2,3, apples => 2).Bool;                   # OUTPUT: «True␤»
    say \().Bool;                                     # OUTPUT: «False␤»

=head2 method Capture

Defined as:

    method Capture(Capture:D: --> Capture:D)

Returns itself, i.e. the invocant.

    say \(1,2,3, apples => 2).Capture; # OUTPUT: «\(1, 2, 3, :apples(2))␤»

=head2 method Numeric

Defined as:

    method Numeric(Capture:D: --> Int:D)

Returns the number of positional elements in the Capture.

    say \(1,2,3, apples => 2).Numeric;                # OUTPUT: «3␤»

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
